package fileProcessing.PreprocessingAnalysis;

import java.awt.Label;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import audit.AuditWriter;

import userInterface.GUIController;
import userInterface.MainPage;

import main.Main;

import fileProcessing.ParsingException;
import fileProcessing.preprocessorException;
/**
 * Discover the header line. Present finding to the user and ask for approval.
 * @author Andrew
 *
 */
public class FindHeaderLine {
	public int headerLine = 0;//0 will be either default or no header line.
	public String headerLineString = "";//Store the matches for later reference.
	private String filename;
	private BufferedReader newReader;
	public int lineNum = -1;
	public static AuditWriter audit;
	
	public FindHeaderLine(String fname) throws preprocessorException, ParsingException{
		//Present user with first 5 lines which contain those fields.
		//Ask for response to determine which line if any is the header.
		//If user enters 6 then set as default fail to parse file as embedded fields.
		filename = fname;
		audit = AuditWriter.getAuditWriter();
		try {
			newReader = new BufferedReader(new FileReader(filename));
		} catch (FileNotFoundException e) {
			throw new preprocessorException("File not found.");
		}
		parseFile();
	}
	
	private void parseFile() throws preprocessorException{
		//Find first 5 lines after first 2 of the file which contain keywords. 
		//Ask user for input.
		String temp;
		int i=1;
		ArrayList<Integer> keyWordsFound = new ArrayList<Integer>();
		try{
			temp = newReader.readLine();
			while(temp != null){
				if(i>2){
					keyWordsFound.add(parseLine(temp));
				}
				else{
					keyWordsFound.add(0);
				}
				temp = newReader.readLine();
				i++;
			}
		} catch (IOException e){
			throw new preprocessorException("error caught while attempting to parse file for structure.");
		}
		setHeaderLine(keyWordsFound.size(),keyWordsFound);
	}
	/**
	 * Look through list of lines and ask to see the first 5 after the first two which contain keyword hits.
	 * @param fileFirstQuarter
	 * @param keyWordsFound
	 * @throws preprocessorException 
	 */
	private void setHeaderLine(int maxLimit, ArrayList<Integer> keyWordsFound) throws preprocessorException {
		int limit = 0;
		ArrayList<Integer> possibleMatches = new ArrayList<Integer>();
		
		for(int i = 0;i<maxLimit;i++){
			if((keyWordsFound.get(i)>0) && limit < 5){
				limit++;
				lineNum = i;
				possibleMatches.add(i+1);
			}
		}
//		if(limit>0)
			try {
				getUserDecision(possibleMatches);
			} catch (ParsingException e) {

			}
//		else{
//			System.out.println("No header lines were identified, maybe the field names could not be recognized...");
//			System.out.println("Would you like to provide new field names to look for and search again?(y\\n)");
//			Scanner userIn = new Scanner(System.in);
//			if(userIn.next().equalsIgnoreCase("y")){
//				MainPage.fieldMatcher.newFieldConstructor();
//				parseFile();
//			}
//		}
	}
	private String getPossibleHeaders(ArrayList<Integer> possibleMatches) throws preprocessorException {
		String headerOptions = "<html>";
		int count = 1;
		for(int match : possibleMatches) {
				headerOptions += "(" + count + ") " + seek(match-1) + "<p>";
				count++;
		}
		return headerOptions;
	}
	private void getUserDecision(ArrayList<Integer> possibleMatches) throws preprocessorException, ParsingException {
		
		if(lineNum >= 0) {
			JFrame frame = new JFrame();
			int count = 0;
			Object[] possibleHeaders = new Object[possibleMatches.size()+1];
			for(int match : possibleMatches) {
				possibleHeaders[count] = "(" + (count+1) + ") " + seek(match-1);
				count++;
			}
			possibleHeaders[count] = "No Header Line";

			String n = (String)JOptionPane.showInputDialog(frame,
									"<html>Please specify which of the lines below is a header line.<p>" + getPossibleHeaders(possibleMatches),
									"Specify Header Line",
									JOptionPane.PLAIN_MESSAGE,
									null,
									possibleHeaders,
									possibleHeaders[0]
									);
		
			if(n != null) {
				if(n.equalsIgnoreCase("No Header Line")) {
					audit.writeToAudit("Parsing without header");
					GUIController.getMainPage().setStatus("Parsing without header\n");
				}
				else {
					headerLine = possibleMatches.get(Integer.parseInt(n.substring(1, 2)) - 1);
					headerLineString = seek(headerLine-1);
					audit.writeToAudit("Header line identified as: " + headerLineString);
				}
			}
		}
	}

	/**
	 * Return the line requested.
	 * @param lineNumber
	 * @throws preprocessorException 
	 */
	private String seek(int lineNumber) throws preprocessorException {
		try{
			newReader.close();
			newReader = new BufferedReader(new FileReader(filename));
			String line;
			for(int i=0;i<lineNumber;i++)
				newReader.readLine();
			line = newReader.readLine();
			return line;
		} catch (IOException e){
			throw new preprocessorException("Error caught while seeking in structure class.");
		}
	}
	/**
	 * Parses a single line to determine the number of fields contained therein.
	 * @param line Line to parse.
	 * @return
	 */
	private int parseLine(String line) {
		int lineLength = line.length(),temp;
		int matchLength = 0,numberOfHits = 0,tempLength = 0;
		String tempS;
		String line1 = line.toLowerCase().replaceAll("\\P{Alpha}", " ").replaceAll("\\s+", " ");
			for(String s : MainPage.fieldMatcher.getHeaderLineCheck()){
				tempS = s;
				if(tempS.contains("\\s*"))
					tempS = tempS.replace("\\s*", "");
				if(tempS.contains("[a-z]*"))
					tempS = tempS.replace("[a-z]*", "");
				tempLength = tempS.length();
				
				temp = findMatches(s,line1);
				if(temp > 0){
					numberOfHits += temp;
					matchLength+= tempLength;
					line1.replace(tempS, "");
				}
			}
			for(String s1 : MainPage.fieldMatcher.getCustomHeaderLineCheck()){
				tempS = s1;
				if(tempS.contains("\\s*"))
					tempS = tempS.replace("\\s*", "");
				if(tempS.contains("[a-z]*"))
					tempS = tempS.replace("[a-z]*", "");
				tempLength = tempS.length();
				
				temp = findMatches(s1,line1);
				if(temp > 0){
					numberOfHits += temp;
					matchLength+= tempLength;
					line1.replace(tempS, "");
				}
			}
		if((((double)matchLength/lineLength) > 0.60) && (numberOfHits > 1)){
			return numberOfHits;
		}
		else
			return 0;
	}
	
	private int findMatches(String regex,String line){
		int result = 0;
		
		Pattern fieldPattern = Pattern.compile("("+regex+")",Pattern.CASE_INSENSITIVE);
		Matcher fieldMatcher = fieldPattern.matcher(line);
		
		while(fieldMatcher.find()){
			result++;
			}
		return result;
	}
}
